package main

import (
	"K8sCodePlatform/src/clients"
	"K8sCodePlatform/src/middlewares"
	"K8sCodePlatform/src/models"
	"context"
	"fmt"
	"io/ioutil"
	v1 "k8s.io/api/core/v1"
	"log"
	"time"

	"github.com/gin-gonic/gin"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func main() {
	k8sClient := clients.InitK8sConfig()
	gormClient := clients.InitGorm()
	r := gin.New()
	r.Use(middlewares.Cors(), middlewares.ErrorHandler())
	// vue登录接口
	r.POST("/vue-admin-template/user/login", func(c *gin.Context) {
		loginRequest := models.NewLoginUserModel()
		if err := c.ShouldBindJSON(&loginRequest); err != nil {
			log.Println(err)
		}
		loginSelectRow := models.NewLoginUserModel()
		gormClient.Model(&models.LoginUserModel{}).Where("username = ?", loginRequest.Username).First(&loginSelectRow)
		if loginRequest.Password != loginSelectRow.Password {
			c.AbortWithStatusJSON(403, gin.H{
				"code": 0,
				"data": "password error",
			})
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": gin.H{
				"token": "admin-token",
			},
		})
	})
	r.POST("/vue-admin-template/user/logout", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"code": 20000,
			"data": "success",
		})
	})
	r.GET("/vue-admin-template/user/info", func(c *gin.Context) {
		c.Header("Content-type", "application/json")
		c.String(200, `{"code":20000,"data":{"roles":["admin"],
		"introduction":"I am a super administrator","avatar":"https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif","name":"Super Admin"}}`)
	})
	// k8s相关接口
	r.GET("/api", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"code": 20000,
			"data": "this is gin api",
		})
	})
	r.GET("/api/deployments", func(c *gin.Context) {
		ns := c.DefaultQuery("ns", "k8scode")
		deps, err := k8sClient.AppsV1().Deployments(ns).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			log.Fatal(err)
		}
		ret := make([]*models.Deployment, 0)
		for _, item := range deps.Items {
			ret = append(ret, &models.Deployment{
				Name:      item.Name,
				NameSpace: item.Namespace,
				Replicas: [3]int32{
					item.Status.Replicas,
					item.Status.AvailableReplicas,
					item.Status.UnavailableReplicas,
				},
				Images:     item.Spec.Template.Spec.Containers[0].Name,
				IsComplete: item.Status.Replicas == item.Status.AvailableReplicas,
				Message: func() string {
					for _, c := range item.Status.Conditions {
						if string(c.Type) == "Available" && string(c.Status) != "True" {
							return c.Message
						}
					}
					return ""
				}(),
				CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
			})
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": ret,
		})
	})
	r.GET("/api/svc", func(c *gin.Context) {
		ns := c.DefaultQuery("ns", "k8scode")
		svclist, err := k8sClient.CoreV1().Services(ns).List(context.Background(), metav1.ListOptions{})
		if err != nil {
			log.Fatal(err)
		}
		ret := make([]*models.ServiceModel, 0)
		for _, item := range svclist.Items {
			ret = append(ret, &models.ServiceModel{
				Name:       item.Name,
				NameSpace:  item.Namespace,
				CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
			})
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": ret,
		})
	})
	r.GET("/api/ingress-nginx", func(c *gin.Context) {
		ns := c.DefaultQuery("ns", "k8scode")
		ret := make([]*models.IngressModel, 0)
		ingressList := k8sClient.NetworkingV1().Ingresses(ns)
		list, err := ingressList.List(context.Background(), metav1.ListOptions{})
		if err != nil {
			log.Fatal(err)
		}
		for _, item := range list.Items {
			ret = append(ret, &models.IngressModel{
				Name:       item.Name,
				NameSpace:  item.Namespace,
				CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
				Host:       item.Spec.Rules[0].Host,
			})
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": ret,
		})
	})
	r.GET("/api/deployment/get-pods", func(c *gin.Context) {
		ns := c.Query("ns")
		deployment := c.Query("dep")
		podsRet := make([]string, 0)
		pods, err := k8sClient.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{
			LabelSelector: fmt.Sprintf("app=%s", deployment),
		})
		if err != nil {
			c.JSON(404, gin.H{
				"code": 20000,
				"data": "error label",
			})
		}
		for _, pod := range pods.Items {
			podsRet = append(podsRet, pod.Name)
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": podsRet,
		})
	})
	r.GET("/api/ns", func(c *gin.Context) {
		nsItems, err := k8sClient.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
		nsRet := make([]string, 0)
		if err != nil {
			log.Fatal(err)
		}
		for _, item := range nsItems.Items {
			nsRet = append(nsRet, item.Name)
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": nsRet,
		})
	})
	r.GET("/api/pod-logs", func(c *gin.Context) {
		ns := c.DefaultQuery("ns", "k8scode")
		podname := c.Query("podname")
		opt := &v1.PodLogOptions{TailLines: func() *int64 {
			value := int64(500)
			return &value
		}()}
		req := k8sClient.CoreV1().Pods(ns).GetLogs(podname, opt)
		podLog, err := req.Stream(context.Background())
		if err != nil {
			c.JSON(200, gin.H{
				"code":    20000,
				"message": "Error streaming logs",
			})
		}
		defer podLog.Close()
		logData, err := ioutil.ReadAll(podLog)
		if err != nil {
			log.Fatal("io err: ", err)
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": string(logData),
		})
	})
	// gorm相关接口
	r.POST("/api/project/create", func(c *gin.Context) {
		projectName := c.PostForm("project_name")
		gitPath := c.PostForm("git_path")
		member_name := c.PostForm("member_name")
		member_role := c.PostForm("member_role")
		createtime := time.Now().Format("2006-01-02 15:04:05")
		project := models.NewProjectModel(projectName, gitPath, createtime)
		gormClient.Where("project_name = ?", projectName).First(&project)
		if projectName == project.ProjectName {
			gormClient.Create(&project)
		}
		gormClient.Create(models.NewMembersModel(member_name, project.ProjectName, member_role))
		c.JSON(200, gin.H{
			"code":    20000,
			"message": "success",
		})
	})
	r.GET("/api/project/list", func(c *gin.Context) {
		type ResultModel struct {
			MemberID    int
			MemberName  string
			MemberRole  string
			ProjectName string
			Createtime  string
		}
		rows, err := gormClient.Table("members").Select("members.member_id", "members.member_name", "members.member_role", "project.project_name", "project.create_time").Joins("left join project on members.project_name = project.project_name").Rows()
		if err != nil {
			log.Fatal(err)
		}
		resultRet := make([]*ResultModel, 0)
		for rows.Next() {
			result := &ResultModel{}
			err := rows.Scan(&result.MemberID, &result.MemberName, &result.MemberRole, &result.ProjectName, &result.Createtime)
			if err != nil {
				log.Fatal(err)
			}
			resultRet = append(resultRet, result)
		}
		c.JSON(200, gin.H{
			"code": 20000,
			"data": resultRet,
		})
	})
	r.Run(":8080")
}
